//:C12:OverloadingUnaryOperators.cpp
#include <iostream>
using namespace std;
// Non-member functions:
class Integer
{
    long i;
    Integer *This(){ return this;}
    public:
        Integer(long ll = 0) : i(ll){}  
        // No side effects takes const & argument:
        friend const Integer& operator+(const Integer &a);
        friend const Integer  operator-(const Integer &a);
        friend const Integer operator~(const Integer &a);
        friend Integer* operator&(Integer &a);
        friend int operator!(const Integer &a);
        // Side effects have non-const & argument:
        // Prefix:
        friend const Integer& operator++(Integer &a);
        // Postfix:
        friend const Integer operator++(Integer &a, int);
        // Prefix:
        friend const Integer& operator--(Integer &a);
        // Postfix:
        friend const Integer operator--(Integer &a, int);
};

// Global operators:
const Integer & operator+(const Integer &a)
{
    cout << "+Integer\n";
    return a;    // Unary + has no effect
}

const Integer operator-(const Integer &a)
{
    cout << "-Integer\n";
    return Integer(-a.i);
}

const Integer operator~(const Integer &a)
{
    cout << "~Integer\n";
    return Integer(~a.i);
}

Integer * operator&(Integer &a)
{
    cout << "&Integer\n";
    return a.This();    // &a is recursive!
}

int operator!(const Integer &a)
{
    cout << "!Integer\n";
    return !a.i;
}

// Prefix; return incrmented value
const Integer & operator++(Integer &a)
{
    cout << "++Integer\n";
    a.i++;
    return a;
}

// Postfix; return the value before increment
const Integer operator++(Integer &a, int i)
{
    cout << "Integer++\n";
    Integer before(a.i);
    a.i++;
    return before;
}

// prefix; return decremented value 
const Integer & operator--(Integer &a)
{
    cout << "--Integer\n";
    a.i--;
    return a;
}
// Postfix; return the value before decrement
const Integer operator--(Integer &a, int i)
{
    cout << "Integer--\n";
    Integer before(a.i);
    a.i--;
    return before;
}

// Show that the overload operators work:
void f(Integer a)
{
    +a;
    -a;
    ~a;
    Integer * ip = &a;
    !a;
    ++a;
    --a;
    a--;
}

// Member functions (implicit "this")
class Byte
{
    unsigned char b;
    public:
        Byte(unsigned char bb = 0) : b(bb){}
        // No side effects: const member function
        const Byte & operator+() const
        {
            cout << "+Byte\n";
            return *this;
        }

        const Byte operator-() const
        {
            cout << "-Byte\n";
            return Byte(-b);
        }

        const Byte operator~() const
        {
            cout << "~Byte\n";
            return Byte(~b);
        }

        Byte operator!() const
        {
            cout << "!Byte\n";
            return Byte(!b);
        }

        Byte * operator&()
        {
            cout << "&Byte\n";
            return this;
        }

        // Side effects: non-const member function:
        const Byte& operator++()
        {    // Prefix
            cout << "Byte++\n";
            Byte before(b);
            b++;
            return *this;
        }

        const Byte operator++(int)
        {    // Postfix
            cout << "Byte++\n";
            Byte before(b);
            b++;
            return before;
        }

        const Byte& operator--()
        {    // Prefix
            cout << "--Byte\n";
            --b;
            return *this;
        }

        const Byte operator--(int)
        {    // Postfix
            cout << "Byte--\n";
            Byte before(b);
            --b;
            return before;
        }
 };

 void g(Byte b)
 {
     +b;
     -b;
     ~b;
     ++b;
     b++;
     --b;
     b--;
 }

int main(void)
{
    Integer a;
    f(a);
    Byte b;
    g(b);
}
